<!-- 表单省市区联动公共组件 -->
<script lang="ts" setup name="address-item">
import axios from 'axios'
import { ElCol, ElInput, ElOption, ElRow, ElSelect } from 'element-plus'
import { computed, onBeforeMount, onMounted, ref, toRefs, watch, watchEffect } from 'vue'

type AddressValue = {
    provinceCode: string
    provinceName: string
    cityCode: string
    cityName: string
    areaCode: string
    areaName: string
    address: string
}

const props = defineProps<{
    modelValue: string
}>()
const emits = defineEmits<{
    'update:modelValue': [value: string]
    'change': [value: AddressValue]
}>()

console.log('🚀 ~ props:', props)

const { modelValue } = toRefs(props)

// 内部状态
const province = ref('')
const city = ref('')
const area = ref('')
const address = ref('')

// 地址对象
const addressObj = ref<AddressValue>({
    provinceCode: '',
    provinceName: '',
    cityCode: '',
    cityName: '',
    areaCode: '',
    areaName: '',
    address: '',
})

export type AreaList = {
    areaList: AreaList[]
    code: string
    level: number
    name: string
}
const provinceList = ref<AreaList[]>([])
const cityList = ref<AreaList[]>([])
const areaList = ref<AreaList[]>([])

// 获取到JSON数据
async function getProvinceList() {
    const res = await axios.get<AreaList[]>(
        'https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/area.json',
    )
    provinceList.value = res.data
    // 数据加载完成后，如果有初始值则进行回显
    if (modelValue.value) {
        initAddressValue()
    }
}

// 初始化地址值
function initAddressValue() {
    if (!modelValue.value)
        return

    const [p, c, a, addr] = modelValue.value.split(',')
    console.log('🚀 ~ initAddressValue ~ p, c, a, addr:', p, c, a, addr)

    // 设置省份
    province.value = p
    // 设置城市
    city.value = c
    // 设置区域
    area.value = a
    // 设置详细地址
    address.value = addr || ''

    // 查找省份对应的城市列表
    const provinceItem = provinceList.value.find(item => item.code === p.split('-')[0])
    if (provinceItem) {
        cityList.value = provinceItem.areaList

        // 查找城市对应的区域列表
        const cityItem = cityList.value.find(item => item.code === c.split('-')[0])
        if (cityItem) {
            areaList.value = cityItem.areaList
        }
    }
}

onBeforeMount(async () => {
    await getProvinceList()
})

// 监听 modelValue 变化
// watch(modelValue, (newVal) => {
//     console.log('🚀 ~ watch ~ modelValue:', newVal)

//     if (newVal && provinceList.value.length > 0) {
//         initAddressValue()
//     }
// })

// 修改 modelValue 的监听
watchEffect(async () => {
    // 确保有值且省份列表已加载
    if (modelValue.value && provinceList.value.length > 0) {
        console.log('watchEffect modelValue:', modelValue.value)
        await initAddressValue()
    }
})

// 监听省份的值改变调用的函数
watch(province, (newData: any) => {
    console.log('🚀 ~ watch province ~ newData:', newData)
    if (!newData) {
        cityList.value = []
        city.value = ''
        area.value = ''
        address.value = ''
    }
    else {
        const provinceCode = newData.split('-')[0]
        const provinceItem = provinceList.value.find(item => item.code === provinceCode)
        if (provinceItem) {
            cityList.value = provinceItem.areaList
            // 只有在手动选择省份时才清空城市和区域
            if (newData !== modelValue.value?.split(',')[0]) {
                city.value = ''
                area.value = ''
            }
        }
    }
}, { immediate: true })

// 监听 市 的值改变调用的函数
watch(city, (newData: any) => {
    console.log('🚀 ~ watch city ~ newData:', newData)
    if (!newData) {
        areaList.value = []
        area.value = ''
        address.value = ''
        return
    }

    const cityCode = newData.split('-')[0]
    const cityItem = cityList.value.find(item => item.code === cityCode)
    if (cityItem) {
        areaList.value = cityItem.areaList
        // 只有在手动选择城市时才清空区域
        if (newData !== modelValue.value?.split(',')[1]) {
            area.value = ''
            address.value = ''
        }
    }
}, { immediate: true })

const cityAble = computed(() => {
    return !province.value
})
const areaAble = computed(() => {
    return !city.value
})
const addressAble = computed(() => {
    return !area.value
})

// 监听地址变化
watch([province, city, area, address], ([newProvince, newCity, newArea, newAddress]) => {
    console.log('🚀 ~ watch address ~ newProvince, newCity, newArea, newAddress:', newProvince, newCity, newArea, newAddress)

    // 确保所有值都存在
    if (!newProvince || !newCity || !newArea || !newAddress) {
        emits('update:modelValue', '')
        // 触发 change 事件，返回完整对象
        emits('change', {
            provinceCode: '',
            provinceName: '',
            cityCode: '',
            cityName: '',
            areaCode: '',
            areaName: '',
            address: '',
        })
    }
    else {
        // 解析省市区编码和名称
        const [provinceCode, provinceName] = newProvince.split('-')
        const [cityCode, cityName] = newCity.split('-')
        const [areaCode, areaName] = newArea.split('-')

        // 更新地址对象
        addressObj.value = {
            provinceCode,
            provinceName,
            cityCode,
            cityName,
            areaCode,
            areaName,
            address: newAddress || '',
        }

        // 触发更新事件，保持原有的字符串格式
        const str = [provinceName, cityName, areaName, newAddress].join(',')
        emits('update:modelValue', str)
        // 触发 change 事件，返回完整对象
        emits('change', addressObj.value)
    }
}, { deep: true })
</script>

<template>
    <ElRow class="address-item">
        <ElCol :span="2">
            <ElSelect v-model="province"
                      clearable
                      placeholder="省"
            >
                <ElOption v-for="item in provinceList"
                          :key="item.code"
                          :label="item.name"
                          :value="`${item.code}-${item.name}`"
                />
            </ElSelect>
        </ElCol>

        <ElCol :span="2"
               ml-10
        >
            <ElSelect v-model="city"
                      clearable
                      placeholder="市"
                      :disabled="cityAble"
            >
                <ElOption v-for="item in cityList"
                          :key="item.code"
                          :label="item.name"
                          :value="`${item.code}-${item.name}`"
                />
            </ElSelect>
        </ElCol>

        <ElCol :span="2"
               ml-10
        >
            <ElSelect v-model="area"
                      clearable
                      placeholder="区"
                      :disabled="areaAble"
            >
                <ElOption v-for="item in areaList"
                          :key="item.code"
                          :label="item.name"
                          :value="`${item.code}-${item.name}`"
                />
            </ElSelect>
        </ElCol>

        <ElCol :span="9"
               ml-10
        >
            <ElInput v-model.tirm="address"
                     :disabled="addressAble"
                     placeholder="请输入详细地址"
            />
        </ElCol>
    </ElRow>
</template>

<style lang="less">
.address-item {
    width: 100%;
}
</style>
